package cn.good.yan.service.t8;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 8. ThreadLocal
 * 使用
 * static ThreadLocal<Object> threadLocal = new ThreadLocal<>();
 * 初始化
 * private static final ThreadLocal<Object> threadLocal = ThreadLocal.withInitial(Object::new);
 * private static final ThreadLocal<Object> threadLocal = ThreadLocal.withInitial(()->{初始化的值});
 * 设置线程本地变量的内容
 * threadLocal.set(user);
 * 获取线程本地变量的内容
 * threadLocal.get();
 * # 移除线程本地变量
 * threadLocal.remove();
 *
 * @author shengren.yan
 * @create 2024-04-03
 */
public class ThreadLocal1 {

    // saleVolume.get() 获取当前线程的局部变量中的值
    // withInitial 创建一个线程局部变量、初始值
    // saleVolume.remove() 删除此线程局部变量的当前线程值
    public static void main(String[] args) throws InterruptedException {
        House house = new House();
        // 创建5个线程
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                int size = new Random().nextInt(5) + 1; // 随机数，每个线程生成的随机数
                try {
                    for (int j = 1; j <= size; j++) {
                        // synchronized 方式进行累加
                        house.saleHouse();
                        // ThreadLocal 方式进行累加 - 统计出每个线程的
                        house.saleVolumeByThreadLocal();
                    }
                    // 获取最新值
                    System.out.println(Thread.currentThread().getName() + "\t" + "【线程】 号销售卖出：" + house.saleVolume.get());
                } finally {
                    // 避免内存泄露
                    house.saleVolume.remove();
                }
            }, String.valueOf(i)).start();
        }

        // 暂停毫秒
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName() + "\t" + "共计卖出多少套： " + house.saleCount);
    }

}

// 资源类
class House {
    int saleCount = 0;

    public synchronized void saleHouse() {
        ++saleCount;
    }

    // 旧方法的：初始化 （默认值是0）
    /*ThreadLocal<Integer> saleVolume = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue(){
            return 0;
        }
    };*/
    // 新方法的：初始化 （默认值是0）
    ThreadLocal<Integer> saleVolume = ThreadLocal.withInitial(() -> 0);

    public void saleVolumeByThreadLocal() {
        // 获取该现场的值，进行+1    ---- saleCount一致累加
        saleVolume.set(1 + saleVolume.get());
    }

}